package com.sudo.service.admin.service.impl;

import com.github.pagehelper.PageHelper;
import com.sudo.common.enums.SysJobStatus;
import com.sudo.common.task.TaskMethod;
import com.sudo.common.task.TaskUtil;
import com.sudo.common.utils.PagedGridResult;
import com.sudo.dao.admin.entity.SysMethodJob;
import com.sudo.dao.admin.mapper.SysMethodJobMapper;
import com.sudo.dao.admin.model.bo.SysMethodJobBO;
import com.sudo.service.admin.config.CronTaskRegistry;
import com.sudo.service.admin.runnable.BeanMethodRunnable;
import com.sudo.service.admin.service.AdminBaseService;
import com.sudo.service.admin.service.SysMethodJobService;
import com.sudo.service.admin.task.AdminTaskModule;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@Service
public class SysMethodJobServiceImpl extends AdminBaseService implements SysMethodJobService {

    @Resource
    private SysMethodJobMapper sysMethodJobMapper;

    @Resource
    private CronTaskRegistry cronTaskRegistry;

    @Override
    public Map<String,String> getTaskModuleMap() {
        return TaskUtil.getTaskModuleMap();
    }

    @Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Exception.class)
    @Override
    public PagedGridResult querySysMethodJobByPage(SysMethodJobBO sysMethodJobBO) {
        PageHelper.startPage(sysMethodJobBO.getPage(), sysMethodJobBO.getPageSize());
        Example example = new Example(SysMethodJob.class);
        example.orderBy("id").desc();
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(sysMethodJobBO.getBeanName())) {
            criteria.andEqualTo("beanName", sysMethodJobBO.getBeanName());
        }
        if (StringUtils.isNotBlank(sysMethodJobBO.getMethodName())) {
            criteria.andEqualTo("methodName", sysMethodJobBO.getMethodName());
        }
        if (StringUtils.isNotBlank(sysMethodJobBO.getMethodParams())) {
            criteria.andLike("methodParams", "%"+sysMethodJobBO.getMethodParams()+"%");
        }
        if (StringUtils.isNotBlank(sysMethodJobBO.getStatus())) {
            criteria.andEqualTo("status", sysMethodJobBO.getStatus());
        }
        List<SysMethodJob> sysMethodJobList = sysMethodJobMapper.selectByExample(example);
        return setterPagedGrid(sysMethodJobList, sysMethodJobBO.getPage());
    }


    @Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Exception.class)
    public List<SysMethodJob> getSysMethodJobByStatus(String status) {
        Example example = new Example(SysMethodJob.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("status", status);
        return sysMethodJobMapper.selectByExample(example);
    }

    @Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Exception.class)
    @Override
    public SysMethodJob querySysMethodJobById(Integer id) {
        return sysMethodJobMapper.selectByPrimaryKey(id);
    }

    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    @Override
    public int updateSysMethodJobStatus(SysMethodJobBO sysMethodJobBO) {
        SysMethodJob sysMethodJob = new SysMethodJob();
        sysMethodJob.setId(sysMethodJobBO.getId());
        sysMethodJob.setStatus(sysMethodJobBO.getStatus());
        if (!SysJobStatus.RUN.name().equals(sysMethodJob.getStatus())
                && !SysJobStatus.STOP.name().equals(sysMethodJob.getStatus())){
            sysMethodJob.setStatus(SysJobStatus.STOP.name());
        }
        int affectCount = 0;
        //修改SysMethodJob时，判断修改之前的状态，如果状态不一致，则需要关闭或打开正在内存中的定时任务
        SysMethodJob oldSysMethodJob = sysMethodJobMapper.selectByPrimaryKey(sysMethodJobBO.getId());
        if (!oldSysMethodJob.getStatus().equals(sysMethodJob.getStatus())){

            affectCount = sysMethodJobMapper.updateByPrimaryKeySelective(sysMethodJob);

            if (affectCount > 0) {
                //删除old Task
                BeanMethodRunnable beanMethodRunnable = new BeanMethodRunnable(oldSysMethodJob);
                cronTaskRegistry.removeCronTask(beanMethodRunnable);
                //打开
                if (SysJobStatus.RUN.name().equals(sysMethodJob.getStatus())) {
                    cronTaskRegistry.addCronTask(beanMethodRunnable,oldSysMethodJob.getCronExpression());
                }
            }
        }
        return affectCount;
    }

    @Override
    public Map<String, Map<String,TaskMethod>> getMethodAndParamCountList() {
        return TaskUtil.getTaskMethodParamCountMap();
    }

    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    @Override
    public int saveSysMethodJob(SysMethodJobBO sysMethodJobBO, String sessionUser) {
        SysMethodJob sysMethodJob = new SysMethodJob();
        BeanUtils.copyProperties(sysMethodJobBO, sysMethodJob);
        sysMethodJob.setStatus(SysJobStatus.STOP.name());
        LocalDateTime localDateTime = LocalDateTime.now();
        sysMethodJob.setCreateTime(localDateTime);
        sysMethodJob.setUpdateTime(localDateTime);
        return sysMethodJobMapper.insertSelective(sysMethodJob);
    }


    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    @Override
    public int updateSysMethodJobWithNoStatus(SysMethodJobBO sysMethodJobBO) {
        SysMethodJob sysMethodJob = new SysMethodJob();
        BeanUtils.copyProperties(sysMethodJobBO,sysMethodJob);
        if (!SysJobStatus.RUN.name().equals(sysMethodJob.getStatus())
                && !SysJobStatus.STOP.name().equals(sysMethodJob.getStatus())){
            sysMethodJob.setStatus(SysJobStatus.STOP.name());
        }
        sysMethodJob.setBeanName(null);
        sysMethodJob.setMethodName(null);
        sysMethodJob.setStatus(null);
        sysMethodJob.setUpdateTime(LocalDateTime.now());

        return sysMethodJobMapper.updateByPrimaryKeySelective(sysMethodJob);
    }

    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    @Override
    public int deleteSysMethodJob(Integer id) {
        SysMethodJob sysMethodJob = sysMethodJobMapper.selectByPrimaryKey(id);
        int affectCount = 0;
        if (sysMethodJob != null) {
            affectCount = sysMethodJobMapper.deleteByPrimaryKey(id);
            if (affectCount > 0) {
                //删除old Task
                try {
                    BeanMethodRunnable beanMethodRunnable = new BeanMethodRunnable(
                            sysMethodJob.getId(),
                            sysMethodJob.getBeanName(),
                            sysMethodJob.getMethodName()
                    );
                    cronTaskRegistry.removeCronTask(beanMethodRunnable);
                }catch (NoSuchBeanDefinitionException e){
                    e.printStackTrace();
                }
            }
        }
        return affectCount;
    }
}
